<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<!--
 1.app.message修改数据。Vue内部是如何监听message数据的改变？
 * Object.defineProperty -> 监听对象属性的改变

 2.当数据发生改变，Vue是如何知道要通知哪些元素，界面发生刷新
 * 发布订阅者模式
-->

<div id="app">
  {{message}}
  {{message}}
  {{message}}
</div>

<script>
  const obj = {
    message: '哈哈哈',
    name: 'why'
  }

  Object.keys(obj).forEach(key => {
    let value = obj[key]

    //给对象定义属性
    Object.defineProperty(obj,key,{
      set(newValue) {
        console.log('监听' + key + '的改变');
        value = newValue;

        // dep.notify()
      },
      get() {
        console.log('获取' + key + '对应的值');
        return value
      }
    })
  });
  obj.name= 'kobe'

  // 发布者订阅者模式
  // 发布者
  class Dep{
    constructor() {
      this.subs = []
    }

    addSub(wather) {
      this.subs.push(wather)
    }

    notify(){
      this.subs.forEach(item => {
        item.update()
      })
    }
  }

  // 订阅者
  class Watcher{
    constructor(name) {
      this.name = name
    }

    update(){
      console.log(this.name + '发生update');
    }
  }

  const dep = new Dep();
  const w1 = new Watcher('张三')
  dep.addSub(w1)

  const w2 = new Watcher('李四')
  dep.addSub(w2)

  const w3 = new Watcher('王五')
  dep.addSub(w3)

  dep.notify()
</script>

<script src="./node_modules/vue/dist/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '哈哈哈'
    }
  })
</script>
</body>
</html>
